package com.qudian.pay.schedule.controller;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qudian.pay.schedule.enums.ConsoleEnum;
import com.qudian.pay.schedule.enums.StrategyTypeEnum;
import com.qudian.pay.schedule.enums.TaskRunningStatusEntum;
import com.qudian.pay.schedule.model.GroupViewModel;
import com.qudian.pay.schedule.model.ScheduleDistribution;
import com.qudian.pay.schedule.model.TaskModel;
import com.qudian.pay.schedule.model.TaskViewModel;
import com.qudian.pay.schedule.redis.JedisTool;
import com.qudian.pay.schedule.service.IScheduleService;
import com.qudian.pay.schedule.service.MonitorService;
import com.qudian.pay.schedule.util.Constant;

@Controller
public class ScheduleConsoleController {
	
	@Autowired
	private IScheduleService scheduleService;
	
	@Autowired
	private JedisTool jedisTool;
	
	@RequestMapping("/taskInfo")
	public String queryTaskList(Model model) {
		List<TaskModel> taskModels = scheduleService.queryTaskModels();
		List<TaskModel> taskStatusModels = scheduleService.queryTaskStatusModels();
		formatInclude(taskStatusModels, taskModels);
		if (taskStatusModels != null) {
			List<GroupViewModel> groupViewList = buildViewModel(taskStatusModels);
			model.addAttribute("taskInfo", groupViewList);
		}
		return "taskInfo";
	}
	
	private void formatInclude(List<TaskModel> taskStatusModels, List<TaskModel> taskModels) {
		for (int i = 0; i < taskStatusModels.size(); i++)
			if (!taskModels.contains(taskStatusModels.get(i))) {
				TaskModel taskModel = taskStatusModels.remove(i);
				jedisTool.del(Constant.SCHEMA_KEY_PREFIX+taskModel.getSchemaKey());
				i--;
			}
	}
	
	private List<GroupViewModel> buildViewModel(List<TaskModel> taskModels) {
		List<GroupViewModel> groupViewList = Lists.newArrayList();
		Map<String,List<TaskViewModel>> taskViewModelMap;
		if ((taskModels != null) && (!taskModels.isEmpty())) {
			Map<String,String> cronExpressMap = jedisTool.hgetAll(ConsoleEnum.EXPRESSION_KEY.getCode());
			Map<String,List<TaskModel>> taskModelMap = Maps.newHashMap();
			for (TaskModel t : taskModels) {
				List<TaskModel> taskModelL = (List<TaskModel>) taskModelMap.get(t.getTaskTag());
				if (taskModelL == null) {
					taskModelL = Lists.newArrayList();
					taskModelMap.put(t.getTaskTag(), taskModelL);
				}
				if (!taskModelL.contains(t)) {
					taskModelL.add(t);
				}
			}
			List<TaskViewModel> taskViewList = Lists.newArrayList();
			Set<Entry<String, List<TaskModel>>> taskEntrySet = taskModelMap.entrySet();
			for (Map.Entry<String, List<TaskModel>> entry : taskEntrySet) {
				String group = ((TaskModel) ((List<TaskModel>) entry.getValue()).get(0)).getGroup();
				TaskViewModel taskView = new TaskViewModel(group, (String) entry.getKey());
				taskView.setNodes((List<TaskModel>) entry.getValue());
				String expreStr = cronExpressMap.get(entry.getKey());
				if (StringUtils.isNotBlank(expreStr)) {
					taskView.setCornExpress(expreStr);
				}
				taskViewList.add(taskView);
			}
			
			taskViewModelMap = Maps.newHashMap();
			for (TaskViewModel t : taskViewList) {
				List<TaskViewModel> taskViewModelL = (List<TaskViewModel>) taskViewModelMap.get(t.getGroup());
				if (taskViewModelL == null) {
					taskViewModelL = Lists.newArrayList();
					taskViewModelMap.put(t.getGroup(), taskViewModelL);
				}
				if (!taskViewModelL.contains(t)) {
					taskViewModelL.add(t);
				}
			}
			
			Set<String> viewKeys = taskViewModelMap.keySet();
			for (String group : viewKeys) {
				GroupViewModel groupView = new GroupViewModel(group);
				groupView.setTasks((List<TaskViewModel>) taskViewModelMap.get(group));
				groupViewList.add(groupView);
			}
		}
		return groupViewList;
	}
	
	@RequestMapping({ "/saveExp" })
	@ResponseBody
	public Map<String,Object> saveRule(String taskTag, String expression) {
		Map<String,Object> resultMap = Maps.newHashMapWithExpectedSize(3);
		try {
			if (StringUtils.isEmpty(expression))
				scheduleService.saveExpression(taskTag, null);
			else {
				scheduleService.saveExpression(taskTag, expression);
			}
			resultMap.put("status", Integer.valueOf(0));
		} catch (Exception e) {
			resultMap.put("status", Integer.valueOf(1));
			resultMap.put("msg", e.getMessage());
		}
		return resultMap;
	}
	
	@RequestMapping("/dealTask")
	@ResponseBody
	public Map<String,Object> dealTask(String key) {
		Map<String,Object> resultMap = Maps.newHashMapWithExpectedSize(3);
		try {
			TaskModel task = scheduleService.getTaskByTag(Constant.SCHEMA_KEY_PREFIX + key);
			if (task.getStatus().equals(TaskRunningStatusEntum.RUNNING.name())) {
				resultMap.put("status", Integer.valueOf(1));
				resultMap.put("msg", "该任务在执行中");
			} else {
				this.scheduleService.sendMsg(task);
				resultMap.put("status", Integer.valueOf(0));
			}
		} catch (Exception e) {
			resultMap.put("status", Integer.valueOf(1));
			resultMap.put("msg", e.getMessage());
		}
		return resultMap;
	}
	
	@RequestMapping({ "/schedule" })
	public Map<String,Object> scheduleWithRule(String config, String type) {
		Map<String,Object> resultMap = Maps.newHashMapWithExpectedSize(3);
		try {
			String cacheServiceUUID = jedisTool.getValue(ConsoleEnum.UUID_KEY.getCode());
			if (StringUtils.isBlank(cacheServiceUUID)) {
				resultMap.put("status", Integer.valueOf(1));
				resultMap.put("msg", "没有调度在执行！");
			} else if (cacheServiceUUID.equals(MonitorService.getServiceUUID())) {
				if (StringUtils.isBlank(type)) {
					type = jedisTool.getValue("SCHEDULE_TYPE");
				}
				StrategyTypeEnum strategyType = StrategyTypeEnum.valueOf(type);
				
				ScheduleDistribution distribution = this.scheduleService.createDistribution(strategyType);
				
				this.scheduleService.startSchedule(distribution);
				resultMap.put("status", Integer.valueOf(0));
			} else {
				resultMap.put("status", Integer.valueOf(1));
				resultMap.put("msg", "调度不在本应用！");
			}
		} catch (Exception e) {
			resultMap.put("status", Integer.valueOf(1));
			resultMap.put("msg", e.getMessage());
		}
		return resultMap;
	}
}
